package com.twd.allcomponent.i18n.config;

import com.twd.allcomponent.i18n.entity.LocaleLanguage;
import com.twd.allcomponent.i18n.mapper.I18nMessageMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.context.support.AbstractMessageSource;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.util.ObjectUtils;

import javax.annotation.PostConstruct;
import java.text.MessageFormat;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.stream.Collectors;

@Slf4j
//@Component
public class CustomMessageSource extends AbstractMessageSource {
    public static final String REDIS_LOCALE_MESSAGE_KEY = "i18n_message";

    @Value("${spring.application.name}")
    private String appName;

    @Autowired
    private I18nMessageMapper i18nMessageMapper;

    @Autowired
    private RedisTemplate<String,Object>  redisTemplate;
    public CustomMessageSource(RedisTemplate redisTemplate,I18nMessageMapper i18nMessageMapper){
        this.i18nMessageMapper=i18nMessageMapper;
        this.redisTemplate=redisTemplate;
    }
    @PostConstruct
    public void init() {
        log.info("init i18n message...");
        redisTemplate.delete(REDIS_LOCALE_MESSAGE_KEY + ":" + appName);
        this.reload();
    }

    /**
     * 重新加载消息到该类的Map缓存中
     */
    public Map<String, Map<String, String>> reload() {
        Map<String, Map<String, String>> localeMsgMap = (Map<String, Map<String, String>>) redisTemplate.opsForValue().get(REDIS_LOCALE_MESSAGE_KEY + ":" + appName);
        if (localeMsgMap == null || localeMsgMap.isEmpty()) {
            // 加载所有的国际化资源
            localeMsgMap = this.loadAllMessageResources();
            // 缓存到redis
            if (localeMsgMap != null && !localeMsgMap.isEmpty()) {
                redisTemplate.opsForValue().set(REDIS_LOCALE_MESSAGE_KEY + ":" + appName, localeMsgMap);
            }
        }
        return localeMsgMap;
    }

    @Override
    protected MessageFormat resolveCode(String code, Locale locale) {
        String msg = this.getSourceFromCacheMap(code, locale);
        return new MessageFormat(msg, locale);
    }

    @Override
    protected String resolveCodeWithoutArguments(String code, Locale locale) {
        return this.getSourceFromCacheMap(code, locale);
    }

    /**
     * 加载所有的国际化消息资源
     *
     * @return
     */
    private Map<String, Map<String, String>> loadAllMessageResources() {
        // 从数据库中查询所有的国际化资源
        List<LocaleLanguage> localeLanguages = i18nMessageMapper.selectList(null);
        Map<String, Map<String, String>> collect = localeLanguages.stream().collect(Collectors.groupingBy(
                // 根据国家地区分组
                LocaleLanguage::getLocale,
                // 收集为Map,key为code,msg为信息
                Collectors.toMap(LocaleLanguage::getCode, LocaleLanguage::getMessage)
        ));
        return collect;
    }

    /**
     * 缓存Map中加载国际化资源
     *
     * @param code
     * @param locale
     * @return
     */
    private String getSourceFromCacheMap(String code, Locale locale) {
        // 判断如果没有值则会去重新加载数据
        Map<String, Map<String, String>> localeMsgMap = this.reload();
        String language = ObjectUtils.isEmpty(locale) ? LocaleContextHolder.getLocale().getLanguage() : locale.getLanguage();
        // 获取缓存中对应语言的所有数据项
        Map<String, String> propMap = localeMsgMap.get(language);
        if (!ObjectUtils.isEmpty(propMap) && propMap.containsKey(code)) {
            // 如果对应语言中能匹配到数据项，那么直接返回
            return propMap.get(code);
        }
        // 如果找不到国际化消息,就直接返回code
        return code;
    }
}
